/*
 * @Author: xiaosihan
 * @Date: 2022-03-20 20:55:43
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2024-04-23 00:07:22
 */
import { BufferGeometry, Camera, Clock, Color, FrontSide, Group, Material, Mesh, PlaneGeometry, Scene, ShaderChunk, ShaderMaterial, Sprite, Vector3, WebGLRenderer } from "three";
import SpriteText2 from "three-base/SpriteText2";

//标记点
export default class Mark extends Mesh {

    constructor(text: string = "mark") {
        super(Mark.geometry);
        this.setSpriteText(text);
        this.name = text;
    }

    static geometry = (() => {
        const planeGeo = new PlaneGeometry(0.18, 0.18, 1, 1);
        planeGeo.rotateX(Math.PI);
        return planeGeo;
    })();

    //three事件
    userData = {
        cursor: "pointer",
        enableEvent: true,
    };

    spriteTextOnFront = true;

    //名称文本
    spriteText = (() => {
        const spriteText = new SpriteText2("123");
        spriteText.color = "#111111";
        spriteText.backgroundColor = "#ffffff";
        spriteText.borderColor = "#cccccc";
        spriteText.borderWidth = 0;
        spriteText.borderRadius = 4;
        spriteText.padding = 8;
        spriteText.renderOrder = 1;
        spriteText.material.depthTest = false;
        spriteText.scale.multiplyScalar(0.01);
        this.add(spriteText); // 暂时不显示地名
        return spriteText;
    })();

    //设置名称
    setSpriteText(text: string) {
        this.spriteText.text = text;
        this.spriteText.scale.multiplyScalar(0.01);
    }

    showSpriteText = true;

    //设置标签的显示
    setShowSpriteText(show: boolean) {
        this.showSpriteText = show;
    }

    // 设置颜色
    setColor(color: `#${string}`) {
        this.material.uniforms.color.value.set(color);
    }

    material = new ShaderMaterial({
        uniforms: {
            frame: { value: 0 },
            // color: { value: new Color("#1970dd") }
            color: { value: new Color("#61FDFF") }
        },
        vertexShader: `
            ${ShaderChunk.common}
            ${ShaderChunk.logdepthbuf_pars_vertex}
            varying vec2 vUv;
            void main() {
                vUv = uv;
                gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
                ${ShaderChunk.logdepthbuf_vertex}
            }
        `,
        fragmentShader: `
            ${ShaderChunk.logdepthbuf_pars_fragment}
            uniform float frame;
            uniform vec3 color;
            varying vec2 vUv;

            float pi = 3.1415926;

            float lineWidth = 0.05;

            vec3 fragColor(){
                 return color;
            }

            float opacity1(){

                vec2 center = vec2(0.5);

                float distanceToCenter = distance( center, vUv );

                float rang = fract(frame / 200.0) / 2.0;

                float opacity = 0.0;

                if(distanceToCenter < (rang - lineWidth) ){
                    opacity =  0.6;
                }else{
                    opacity =  0.0;
                }

                opacity = max(opacity, (1.0 - smoothstep( 0.0 , lineWidth , abs(distanceToCenter - (rang - lineWidth) )  ) ) );

                opacity *= cos(rang * pi);

                return opacity;
            }

            float opacity2(){

                vec2 center = vec2(0.5);

                float distanceToCenter = distance( center, vUv );

                float rang = fract(frame / 200.0 + 0.5) / 2.0;

                float opacity = 0.0;

                if(distanceToCenter < (rang - lineWidth) ){
                    opacity =  0.6;
                }else{
                    opacity =  0.0;
                }

                opacity = max(opacity, (1.0 - smoothstep( 0.0 , lineWidth , abs(distanceToCenter - (rang - lineWidth) )  ) ) );

                opacity *= cos(rang * pi);

                return opacity;
            }

            void main() {
                ${ShaderChunk.logdepthbuf_fragment}
                gl_FragColor = vec4(fragColor(),max(  opacity1(), opacity2() ));

                if(gl_FragColor.a < 0.1){
                    discard;
                }

            }
        `,
        // blending: NoBlending, // 渲染时不与背景融合计算 直接替换
        side: FrontSide,
        depthTest: true,
        depthWrite: true,
        transparent: true
    });

    renderOrder = 1;

    normal = new Vector3();
    cameraDirection = new Vector3();
    hideSpriteText = false; // 隐藏文本弹窗
    clock = new Clock();

    onBeforeRender = (renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, material: Material, group: Group,) => {
        this.material.uniforms.frame.value += (this.clock.getDelta() * 100);

        //如果标记转到背面去了,就隐藏弹窗文本
        this.getWorldDirection(this.normal);
        this.getWorldPosition(this.cameraDirection);
        this.cameraDirection.sub(camera.position).normalize();
        const angle = this.normal.angleTo(this.cameraDirection);
        this.spriteTextOnFront = (angle < (Math.PI / 2));
        this.spriteText.visible = this.spriteTextOnFront && this.showSpriteText;

    }



}
